home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 12 / Mac Magazin and MacEasy Magazine CD - Issue 12.iso / Sharewarebibliothek / Anwendungen / Wissenschaft & Technik / Finder Marquee ƒ / finder_marquee.c < prev    next >
Text File  |  1995-07-10  |  7KB  |  237 lines

  1. /*
  2.  
  3.     Finder Marquee
  4.     by Jordan Zimmerman
  5.     (c)1995 by Altura Software, Inc.
  6.  
  7.     Unlimited use is hereby granted without restriction.  However,
  8.     the author would appreciate credit if possible.  Please send
  9.     comments, questions, bugs, etc. to jordanz@altura.com
  10.     
  11.     This code implements a "rubber band" marquee select rect
  12.     with very smooth drawing in a manner similar to the Mac Finder.
  13.     
  14.     Change History:
  15.     
  16.     1.0.0    07/10/95    JLZ        Created inital C version from existing C++ framework
  17.  
  18. */
  19.  
  20. #include "finder_marquee.h"
  21.  
  22. static void calculate_marquee_r(finder_marquee_rec* marquee_ptr);
  23. static void draw_marquee_r(const finder_marquee_rec* marquee_ptr);
  24. static void make_frame_region(RgnHandle target_rgn_h, const Rect* frame_r_ptr, RgnHandle work_rgn_h);
  25.  
  26.  
  27. //-------------Global Functions------------
  28.  
  29.  
  30. void FinderMarqueeBegin(finder_marquee_rec* marquee_ptr, Point mouse_down_pt)
  31. {
  32.  
  33.     // save the first mouse as our anchor point
  34.     marquee_ptr->pin_pt = mouse_down_pt;
  35.     
  36.     // it's also our current point
  37.     marquee_ptr->current_pt = mouse_down_pt;
  38.  
  39.     // make the marquee_r
  40.     calculate_marquee_r(marquee_ptr);
  41.  
  42.     // allow selections to draw now to avoid and screen turds
  43.     if ( marquee_ptr->change_selection_proc )
  44.     {
  45.         Rect        old_marquee_r = marquee_ptr->marquee_r;
  46.         marquee_ptr->change_selection_proc(marquee_ptr, &old_marquee_r);
  47.     }
  48.     
  49.     // display the first marquee_r - important to have a balance when FinderMarqueeEnd is called
  50.     draw_marquee_r(marquee_ptr);
  51.  
  52. } // FinderMarqueeBegin
  53.  
  54. void FinderMarqueeEnd(finder_marquee_rec* marquee_ptr)
  55. {
  56.  
  57.     // remove the marquee from the screen - 
  58.     // this works because FinderMarqueeBegin drew it
  59.     draw_marquee_r(marquee_ptr);
  60.  
  61. } // FinderMarqueeEnd
  62.  
  63. void FinderMarqueeContinue(finder_marquee_rec* marquee_ptr, Point new_mouse_pt)
  64. {
  65.  
  66.     PenState        pen_state;
  67.     Rect            old_marquee_r;
  68.     RgnHandle        old_rgn_h = NULL;
  69.     RgnHandle        work_rgn_h = NULL;
  70.     RgnHandle        new_rgn_h = NULL;
  71.     RgnHandle        clip_rgn_h = NULL;
  72.     int                success_flag = false;
  73.  
  74.     // avoid flashing step 1 - do nothing if the mouse hasn't moved
  75.     if ( EqualPt(new_mouse_pt, marquee_ptr->current_pt) )
  76.     {
  77.         return;
  78.     }
  79.     clip_rgn_h = NewRgn();
  80.     if ( !clip_rgn_h )
  81.     {
  82.         return;    // can't find 10 bytes!  We're probably already in big trouble
  83.     }
  84.  
  85.     // we'll be messing with the clip, so save it for later restoration
  86.     GetClip(clip_rgn_h);
  87.     
  88.     // save and setup the pen
  89.     GetPenState(&pen_state);
  90.     PenMode(patXor);
  91.     PenPat(&qd.gray);
  92.     
  93.     // save the old marquee_r and setup the new one
  94.     old_marquee_r = marquee_ptr->marquee_r;
  95.     marquee_ptr->current_pt = new_mouse_pt;
  96.     calculate_marquee_r(marquee_ptr);
  97.     
  98.     do
  99.     {
  100.         old_rgn_h = NewRgn();
  101.         if ( !old_rgn_h )
  102.         {
  103.             break;
  104.         }
  105.         work_rgn_h = NewRgn();
  106.         if ( !work_rgn_h )
  107.         {
  108.             break;
  109.         }
  110.         new_rgn_h = NewRgn();
  111.         if ( !new_rgn_h )
  112.         {
  113.             break;
  114.         }
  115.         
  116.         // generate 1 pixel thick outline regions of the old and new marquee_r
  117.         make_frame_region(old_rgn_h, &old_marquee_r, work_rgn_h);
  118.         make_frame_region(new_rgn_h, &marquee_ptr->marquee_r, work_rgn_h);
  119.         
  120.         // get the area in common between the old and the new
  121.         SectRgn(old_rgn_h, new_rgn_h, work_rgn_h);
  122.  
  123.         // set the clip to the old clip minus the common area of the old and new marquee rect        
  124.         DiffRgn(clip_rgn_h, work_rgn_h, work_rgn_h);
  125.         SetClip(work_rgn_h);                            
  126.         
  127.         if ( marquee_ptr->selections_proc && marquee_ptr->selections_proc(marquee_ptr) )
  128.         {
  129.             // If there is a selection, the old marquee must be erased, the selections must be drawn, 
  130.             // and then the new marquee can be drawn.
  131.             FrameRect(&old_marquee_r);
  132.             if ( marquee_ptr->change_selection_proc )
  133.             {
  134.                 marquee_ptr->change_selection_proc(marquee_ptr, &old_marquee_r);
  135.             }
  136.             FrameRect(&marquee_ptr->marquee_r);
  137.         }
  138.         else
  139.         {
  140.             // If there's no selection change, the marquee can be drawn in one step
  141.             // that will erase the old and draw the new.
  142.             UnionRgn(new_rgn_h, old_rgn_h, work_rgn_h);
  143.             PaintRgn(work_rgn_h);    // this will both erase the old and draw the new
  144.         }
  145.     } while ( success_flag++ );    // i.e. do once, set success_flag on exit
  146.     
  147.     if ( !success_flag )
  148.     {
  149.         // memory is evidently very tight, we'll have to live with flashing
  150.         FrameRect(&old_marquee_r);
  151.         if ( marquee_ptr->change_selection_proc )
  152.         {
  153.             marquee_ptr->change_selection_proc(marquee_ptr, &old_marquee_r);
  154.         }
  155.         FrameRect(&marquee_ptr->marquee_r);
  156.     }
  157.     
  158.     // restore clip and pen and then cleanup
  159.     
  160.     SetClip(clip_rgn_h);
  161.     SetPenState(&pen_state);
  162.     
  163.     if ( old_rgn_h )
  164.     {
  165.         DisposeRgn(old_rgn_h);
  166.     }
  167.     if ( work_rgn_h )
  168.     {
  169.         DisposeRgn(work_rgn_h);
  170.     }
  171.     if ( new_rgn_h )
  172.     {
  173.         DisposeRgn(new_rgn_h);
  174.     }
  175.     if ( clip_rgn_h )
  176.     {
  177.         DisposeRgn(clip_rgn_h);
  178.     }
  179.  
  180. } // FinderMarqueeContinue
  181.  
  182.  
  183. //-------------Local Functions-------------
  184.  
  185.  
  186. // calculating the marquee rect isn't as simple as Pt2Rect.  Using Pt2Rect
  187. // causes the pin point to shift around.  This function will calculate a
  188. // correct marquee rect that keeps the pin point in place  
  189. static void calculate_marquee_r(finder_marquee_rec* marquee_ptr)
  190. {
  191.  
  192.     if ( (marquee_ptr->current_pt.h >= marquee_ptr->pin_pt.h) && (marquee_ptr->current_pt.v >= marquee_ptr->pin_pt.v) )    // Quadrant IV
  193.     {
  194.         SetRect(&marquee_ptr->marquee_r, marquee_ptr->pin_pt.h, marquee_ptr->pin_pt.v, marquee_ptr->current_pt.h + 1, marquee_ptr->current_pt.v + 1);
  195.     }
  196.     else if ( (marquee_ptr->current_pt.h <= marquee_ptr->pin_pt.h) && (marquee_ptr->current_pt.v <= marquee_ptr->pin_pt.v) )    // Quadrant I
  197.     {
  198.         SetRect(&marquee_ptr->marquee_r, marquee_ptr->current_pt.h, marquee_ptr->current_pt.v, marquee_ptr->pin_pt.h + 1, marquee_ptr->pin_pt.v + 1);
  199.     }
  200.     else if ( (marquee_ptr->current_pt.h >= marquee_ptr->pin_pt.h) && (marquee_ptr->current_pt.v <= marquee_ptr->pin_pt.v) )    // Quadrant II
  201.     {
  202.         SetRect(&marquee_ptr->marquee_r, marquee_ptr->pin_pt.h, marquee_ptr->current_pt.v, marquee_ptr->current_pt.h + 1, marquee_ptr->pin_pt.v + 1);
  203.     }
  204.     else // Quadrant III
  205.     {
  206.         SetRect(&marquee_ptr->marquee_r, marquee_ptr->current_pt.h, marquee_ptr->pin_pt.v, marquee_ptr->pin_pt.h + 1, marquee_ptr->current_pt.v + 1);
  207.     }
  208.         
  209. } // calculate_marquee_r
  210.  
  211. // outline the marquee rect in Xor gray
  212. static void draw_marquee_r(const finder_marquee_rec* marquee_ptr)
  213. {
  214.  
  215.     PenState            pen_state;
  216.     GetPenState(&pen_state);
  217.  
  218.     PenMode(patXor);    
  219.     PenPat(&qd.gray);
  220.     
  221.     FrameRect(&marquee_ptr->marquee_r);
  222.  
  223.     SetPenState(&pen_state);
  224.  
  225. } // draw_marquee_r
  226.  
  227. // utility to make a 1 pixel thick region of the frame outline of a rect
  228. static void make_frame_region(RgnHandle target_rgn_h, const Rect* frame_r_ptr, RgnHandle work_rgn_h)
  229. {
  230.  
  231.     RectRgn(target_rgn_h, frame_r_ptr);
  232.     CopyRgn(target_rgn_h, work_rgn_h);
  233.     InsetRgn(work_rgn_h, 1, 1);
  234.     DiffRgn(target_rgn_h, work_rgn_h, target_rgn_h);
  235.     
  236. } // make_frame_region
  237.